home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / 7Edit / C Sources / SVEditions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-25  |  41.2 KB  |  1,471 lines  |  [TEXT/MPS ]

  1. /*
  2.     SVEditions.c
  3.     
  4.     Version 3.0d9
  5.     
  6.     Copyright © SRL Data 1992, 1993
  7.     
  8.     All rights reserved
  9.     
  10.     Produced by : SRL Data
  11.     Originally Developed for UK.DTS
  12.  
  13.     The Edition Manager routines from the Menuscripter example.
  14.  
  15.  
  16. Known incomplete bits-:
  17.     i)         Handling the mouse downs for Publishers and Subscribers is not all there-
  18.                 future versions will include double clicking to open the section options dialog,
  19.                 for example.
  20.     ii)     There are problems if an edition is moved from the Finder- there needs to
  21.                 be code added to handle orphaned sections.
  22.     iii)     We need to issue a warning if a document is disposed of containing
  23.                 sections that will be lost.
  24. */
  25.  
  26. /*
  27.     Changes for 3.0d2 :
  28.         10-Feb-92    : NH    :    Tidy up dead vars etc.
  29.         11-Feb-92    :    NH    : Fix bug in read of saved document with sections - ReadSectionRecords
  30.         20-Feb-92 : NH  : Put in new code to handle section position changes due to paste, key etc.
  31.                                                 DoTEPasteSectionRecalc,
  32.                                                 DoTEDeleteSectionRecalc,
  33.                                                 DoTECutSectionRecalc,
  34.                                                 DoTEKeySectionRecalc,        
  35.                                                 KeyOKinSubscriber,
  36.                                                 DoSectionRecalc
  37.         22-Feb-92: NH        : Code the 'styl' part of editions.
  38.         25-Feb-92: NH        : Fix publisher borders clipping.
  39.         26-Feb-92: NH        : Draw Borders to edge of printed page not window.
  40.         27-Feb-92: NH        : gCurrSection zapped.
  41.         28-Feb-92: NH        : PublishText via AppleEvent
  42.         18-Mar-92: NH        : Old comments updates/zapped
  43.         19-Mar-92: NH        : Fix Edition code so finder can open publisher etc.
  44.     
  45.     Changes for 3.0d4 :
  46.          9-Jul-92: NH   : AEInteractWithUser before NewPublisherDialog
  47. */
  48.  
  49. #include <OSUtils.h>
  50. #include <Resources.h>
  51. #include <Errors.h>
  52. #include <AppleEvents.h>
  53.  
  54. #include "SVEditions.h"
  55.  
  56. /**-----------------------------------------------------------------------
  57.         Name:             GetERefCon
  58.         Purpose:        Return the sectHandle (our own type) stored in
  59.                                 the refcon of the SectionRecord.
  60.     -----------------------------------------------------------------------**/
  61.  
  62. #pragma segment  Editions
  63.  
  64. pascal SectHandle GetERefCon(SectionHandle EMSection)
  65.   {
  66.         SectHandle aSectHandle;
  67.  
  68.         aSectHandle = (SectHandle)(*EMSection)->refCon;
  69.         return(aSectHandle);
  70.     }
  71.  
  72. /**-----------------------------------------------------------------------
  73. Name:             SetERefCon
  74. Purpose:        Store a handle to our own SectRecord in the refcon
  75.                         field of the SectionRecord.
  76. -----------------------------------------------------------------------**/
  77.  
  78. #pragma segment  Editions
  79.  
  80. pascal void SetERefCon(SectionHandle EMSection, SectHandle aSectHandle)
  81.   {
  82.         (*EMSection)->refCon = (long)aSectHandle;
  83.     }
  84.  
  85. /**-----------------------------------------------------------------------
  86.         Name:             AddSection
  87.         Purpose:        Add our own section record to the document linked
  88.                                 list.  Set up the first and last section variables.
  89.     -----------------------------------------------------------------------**/
  90.  
  91. #pragma segment  Editions
  92.  
  93. pascal void AddSection(SectHandle newSection, DPtr aDocument)
  94.     {
  95.         /*
  96.             add the section to the document
  97.         */
  98.         aDocument->numSections += 1;
  99.  
  100.         /*
  101.             if not NIL, add the new section to the list after the last element
  102.         */
  103.         
  104.         if (aDocument->lastSection)
  105.             (*(aDocument->lastSection))->fNextSection = newSection;
  106.         else
  107.             aDocument->firstSection = newSection;
  108.         
  109.         aDocument->lastSection       = newSection;
  110.         (*newSection)->fNextSection  = nil;
  111.     }
  112.  
  113. /**-----------------------------------------------------------------------
  114.         Name:             CreateSection
  115.         Purpose:        Create a new section record to hold a Publisher or
  116.                                 Subscriber. Link this to the SectionRecord.
  117.     -----------------------------------------------------------------------**/
  118.  
  119. #pragma segment  Editions
  120.  
  121. pascal void CreateSection(SectionHandle   EMSection,
  122.                                                   short           sectionID,
  123.                                                   short           theStart,
  124.                                                   short           theEnd,
  125.                                                   DPtr            aDocument,
  126.                                                   RgnHandle       theBorder)
  127.  
  128.     {
  129.         SectHandle    newSection;
  130.  
  131.         /*
  132.             create a section and call AddSection to add it to the list
  133.         */
  134.         newSection = (SectHandle)NewHandle(sizeof(SectRec));
  135.         
  136.         if (newSection)
  137.             {
  138.                 (*newSection)->fSectionID   = sectionID;
  139.                 (*newSection)->fNextSection = nil;
  140.                 (*newSection)->fSectHandle  = EMSection;
  141.                 (*newSection)->fStart       = theStart;
  142.                 (*newSection)->fEnd         = theEnd;
  143.                 (*newSection)->fCount       = theEnd - theStart;
  144.                 (*newSection)->fBorderRgn   = theBorder;
  145.                 (*newSection)->fDocument    = aDocument;
  146.  
  147.                 /*
  148.                     put a reference to our section record in the section's refCon field
  149.                 */
  150.                 
  151.                 SetERefCon(EMSection, newSection);
  152.                 AddSection(newSection, aDocument);
  153.             }
  154.     }
  155.  
  156.  /**-----------------------------------------------------------------------
  157.         Name:             DeleteASection
  158.         Purpose:        Delete the section from the list.
  159.                                 Called when 'Cancel Publisher/Subscriber is chosen in
  160.                                 the 'Section Options' dialog.
  161.     -----------------------------------------------------------------------**/
  162.  
  163.     #pragma segment  Editions
  164.  
  165. pascal void DeleteASection(SectHandle sectToDelete, DPtr theDoc)
  166.   {
  167.         SectHandle    currSect;
  168.         SectHandle    prevSect;
  169.  
  170.         currSect = theDoc->firstSection;
  171.         prevSect = nil;
  172.  
  173.         while (currSect)
  174.             {
  175.                 if (currSect == sectToDelete)
  176.                     {
  177.                         /*
  178.                             unlink the section from the list
  179.                         */
  180.                         if (prevSect)
  181.                             (*prevSect)->fNextSection = (*currSect)->fNextSection;
  182.                             
  183.                         if (currSect == theDoc->firstSection)
  184.                             theDoc->firstSection = nil;
  185.                             
  186.                         if (currSect == theDoc->lastSection)
  187.                             theDoc->lastSection = nil;
  188.                     }
  189.                 prevSect = currSect;
  190.                 currSect = (*currSect)->fNextSection;
  191.             }
  192.     }
  193.  
  194. /**-----------------------------------------------------------------------
  195.         Name:             ReadASection
  196.         Purpose:        Read in a section from disk
  197.                                 Read in the rAliasType and rsectionType resources and register
  198.                                 the section with the document.
  199.     -----------------------------------------------------------------------**/
  200.  
  201. #pragma segment  Editions
  202.  
  203. pascal void ReadASection(SectHandle aSectHandle)
  204.   {
  205.         SectionHandle     aSectionHandle;
  206.         AliasHandle         anAlias;
  207.         OSErr               err;
  208.         FSSpec             myFSSpec;
  209.         Boolean             ignore;
  210.  
  211.         /*read in the rAliasType and rSectionType resources*/
  212.                 
  213.         aSectionHandle = (SectionHandle)Get1Resource(rSectionType, (*aSectHandle)->fSectionID);
  214.         err            = HandToHand((Handle *)&aSectionHandle);
  215.         (*aSectHandle)->fSectHandle = aSectionHandle;
  216.         SetERefCon(aSectionHandle, aSectHandle);
  217.                 
  218.         anAlias = (AliasHandle)Get1Resource(rAliasType, (*aSectHandle)->fSectionID);
  219.         err     = HandToHand((Handle *)&anAlias);
  220.         (*aSectionHandle)->alias = anAlias;
  221.                 
  222.         /*now register the section*/
  223.                 
  224.         err = ResolveAlias(nil, (*aSectionHandle)->alias, &myFSSpec, &ignore);
  225.         if (err)
  226.             {
  227.                 ShowError((unsigned char *)"\pResolve Alias", err);
  228.                 return;
  229.             }
  230.                     
  231.         err = RegisterSection(&myFSSpec, aSectionHandle, &ignore);
  232.                 
  233.         if ((err) && (err != notThePublisherWrn) && (err != multiplePublisherWrn))
  234.             {
  235.                 ShowError((unsigned char *)"\pRegisterSection", err);
  236.                 return;
  237.             }
  238.         SetSelectionRgn(((*aSectHandle)->fDocument)->theText, 
  239.                         (*aSectHandle)->fStart, 
  240.                                         (*aSectHandle)->fEnd,
  241.                                         &(*aSectHandle)->fBorderRgn);
  242.         InvalRgn((*aSectHandle)->fBorderRgn);
  243.     }
  244.  
  245. /**-----------------------------------------------------------------------
  246. Name:             ReadAllSectionResources
  247. Purpose:        Call the above routine to read in the resources for
  248.                         each section in the document.
  249. -----------------------------------------------------------------------**/
  250. #pragma segment Editions
  251.  
  252. pascal void ReadAllSectionResources(DPtr aDoc)
  253.   {
  254.         SectHandle  theSection;
  255.  
  256.         /*read in each section resource*/
  257.         
  258.         theSection = aDoc->firstSection;
  259.         while (theSection)
  260.             {
  261.                 ReadASection(theSection);
  262.                 theSection = (*theSection)->fNextSection;
  263.             }
  264.     }
  265.  
  266. /**-----------------------------------------------------------------------
  267. Name:             ReadSectionRecords
  268. Purpose:        Read in all the 'sect' resources and form list
  269.                         of sections in the document.    This is called from the
  270.                         main read document routine.
  271. -----------------------------------------------------------------------**/
  272. #pragma segment  Editions
  273.  
  274. pascal void ReadSectionRecords(DPtr aDoc)
  275.   {
  276.         short         theID;
  277.         SectHandle    aSectHandle;
  278.         OSErr         err;
  279.         short         theCount;
  280.  
  281.         /*read in all the 'sect' resources for our document's sections*/
  282.         
  283.         theCount = aDoc->numSections;
  284.         if (theCount == 0)
  285.             return;
  286.             
  287.         aDoc->numSections = 0;
  288.         for (theID = 1; theID <= theCount; theID++)
  289.             {
  290.                 aSectHandle = (SectHandle)Get1Resource('SECT', theID);
  291.                 err = HandToHand((Handle *)&aSectHandle);
  292.                 
  293.                 /*now add it to the list*/
  294.         
  295.                 if (aSectHandle)
  296.                     AddSection(aSectHandle, aDoc);
  297.         
  298.                 /*here we should recalculate the region for the bounds*/
  299.         
  300.                 (*aSectHandle)->fBorderRgn = NewRgn();
  301.         
  302.                 (*aSectHandle)->fDocument  = aDoc;
  303.             }
  304.     }
  305.  
  306. /**-----------------------------------------------------------------------
  307.         Name:             SaveASection
  308.         Purpose:        Write out the 'sect', rAliasType and rSectionType resources
  309.                                 to file.    Called when the document is saved.
  310.     -----------------------------------------------------------------------**/
  311.  
  312. #pragma segment Editions
  313.  
  314. pascal void SaveASection(SectHandle aSection, short count)
  315.   {
  316.         SectionHandle  EMSection;
  317.         OSErr          err;
  318.         Handle         tempHandle;
  319.  
  320.         HLock((Handle)aSection);
  321.         
  322.         /*save this section as its component rAliasType and rSectionType resource*/
  323.         /*also save as our own section record as a 'sect' resource*/
  324.         
  325.         EMSection  = (*aSection)->fSectHandle;
  326.         tempHandle = (Handle)EMSection;
  327.         err        = HandToHand(&tempHandle);
  328.         
  329.         HLock((Handle)EMSection);
  330.         AddResource(tempHandle, rSectionType, (*EMSection)->sectionID, (unsigned char *)"");
  331.         err = ResError();
  332.         if (err)
  333.             {
  334.                 ShowError((unsigned char *)"\pAddResource- rSectionType", err);
  335.                 return;
  336.             }
  337.  
  338.         /*now add the alias resource*/
  339.         tempHandle = (Handle)(*EMSection)->alias;
  340.         err = HandToHand(&tempHandle);
  341.         AddResource(tempHandle, rAliasType, (*EMSection)->sectionID, (unsigned char *)"");
  342.         if (err)
  343.             {
  344.                 ShowError((unsigned char *)"\pAddResource- rAliasType", err);
  345.                 return;
  346.             }
  347.  
  348.         /*now add our own resource- for now all the record, although we only need a few fields*/
  349.         tempHandle = (Handle)aSection;
  350.         err  = HandToHand(&tempHandle);
  351.         AddResource(tempHandle, 'SECT', count, (unsigned char *)"");
  352.         if (err)
  353.             {
  354.                 ShowError((unsigned char *)"\pAddResource- SECT", err);
  355.                 return;
  356.             }
  357.  
  358.         HUnlock((Handle)aSection);
  359.         HUnlock((Handle)EMSection);
  360.     }
  361.  
  362.  /**-----------------------------------------------------------------------
  363.         Name:             SaveSections
  364.         Purpose:        Called to go down to the section list and call SaveASection
  365.                                 for each one.
  366.     -----------------------------------------------------------------------**/
  367.  
  368. #pragma segment Editions
  369.  
  370. pascal void SaveSections(DPtr aDocument)
  371.   {
  372.         OSErr          err;
  373.         SectHandle     currSection;
  374.         short          count;
  375.  
  376.         /*go down the list and save each of the sections*/
  377.         /*the resource file is already open for writing*/
  378.         
  379.         count = 1;
  380.         err = ResError();
  381.         if (err)
  382.             {
  383.                 ShowError((unsigned char *)"\pHOpenResFile", err);
  384.                 return;
  385.             }
  386.  
  387.         /*now go down the list*/
  388.         currSection = aDocument->firstSection;
  389.         while (currSection)
  390.             {
  391.                 SaveASection(currSection, count);
  392.                 currSection = (*currSection)->fNextSection;
  393.                 count ++;
  394.             }
  395.     }
  396.  
  397. /**-----------------------------------------------------------------------
  398.     Name:             AssocAllSections
  399.     Purpose:        Associate all the sections in a document with the document.
  400.                             Called on a SaveAs.
  401. -----------------------------------------------------------------------**/
  402.  
  403. #pragma segment Editions
  404.  
  405. pascal void AssocAllSections(DPtr theDoc)
  406.   {
  407.         SectHandle    aSection;
  408.         SectionHandle EMSection;
  409.         OSErr         err;
  410.  
  411.         /*called by DoSaveAs.    Make sure sections are registered with this document*/
  412.         aSection = theDoc->firstSection;
  413.         while (aSection)
  414.             {
  415.                 EMSection = (*aSection)->fSectHandle;
  416.                 err = AssociateSection(EMSection, &theDoc->theFSSpec);
  417.                 aSection  = (*aSection)->fNextSection;
  418.             }
  419.     }
  420.  
  421.             
  422. /**-----------------------------------------------------------------------
  423.         Name:             KeyOKinSubscriber
  424.         Purpose:        Detects arrow keys.
  425.  -----------------------------------------------------------------------**/
  426. #define kChLeft        28
  427. #define kChRight    29
  428. #define kChUp            30
  429. #define kChDown      31
  430.  
  431. #pragma segment Editions
  432.     
  433. pascal Boolean KeyOKinSubscriber(char whatKey)
  434.     
  435.     {
  436.         return( (whatKey==kChUp)   || (whatKey==kChDown) ||
  437.                         (whatKey==kChLeft) || (whatKey==kChRight));
  438.         
  439.     } /*KeyOKinSubscriber*/
  440.  
  441. /**-----------------------------------------------------------------------
  442.         Name:             ShiftSection
  443.         Purpose:        Moves a section by howMany characters.
  444.  -----------------------------------------------------------------------**/
  445.  
  446. pascal void ShiftSection(SectHandle whichSection, short howMany)
  447.     {
  448.         (*whichSection)->fStart += howMany;
  449.         (*whichSection)->fEnd   += howMany;
  450.     }  /* ShiftSection */
  451.             
  452. /**-----------------------------------------------------------------------
  453. Name:             DoSectionRecalc
  454. Purpose:        Keeps track of the positions of the sections.
  455. -----------------------------------------------------------------------**/
  456.  
  457. #pragma segment Editions
  458.  
  459. pascal void DoSectionRecalc(DPtr theDoc, short toAdd)
  460.     {
  461.         short        theStartPos;
  462.         short        theEndPos;
  463.         short        oldSectionStart;
  464.         short        oldSectionEnd;
  465.         SectHandle   aSection;
  466.         Boolean      wasChanged;
  467.         GrafPtr      oldPort;
  468.         
  469.         /*
  470.             Work thru all sections -
  471.             1) Those spanning area of modification get modified or zapped
  472.             2) Those after get shifted back or forwards.
  473.             
  474.             Sorry it is so complicated - there's a lot of possibilities
  475.         */
  476.         theStartPos = (*(theDoc->theText))->selStart;
  477.         theEndPos   = (*(theDoc->theText))->selEnd;
  478.         
  479.         aSection = theDoc->firstSection;
  480.         while (aSection)
  481.             {
  482.                 wasChanged = true;
  483.                 
  484.                 oldSectionEnd   = (*aSection)->fEnd;
  485.                 oldSectionStart = (*aSection)->fStart;
  486.                 
  487.                 if (theEndPos < (*aSection)->fStart)
  488.                     ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  489.                 else
  490.                     if (theStartPos == (*aSection)->fStart)
  491.                         if (theEndPos == (*aSection)->fStart)
  492.                             ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  493.                         else
  494.                             if (theEndPos >= (*aSection)->fEnd) /* section becomes pasted text */
  495.                                 (*aSection)->fEnd = (*aSection)->fStart + toAdd;
  496.                             else                                                                    /* insert pasted text */
  497.                                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  498.                     else
  499.                         if (theStartPos< (*aSection)->fStart)
  500.                             (*aSection)->fStart = theStartPos + toAdd; /* move start to end of pasted text */
  501.                         else
  502.                             if (theStartPos <= (*aSection)->fEnd)
  503.                                 if (theEndPos >= (*aSection)->fEnd) /* end of section becomes pasted text */
  504.                                     (*aSection)->fEnd = theStartPos + toAdd ;
  505.                                 else                                                                    /* insert pasted text into section */
  506.                                     (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  507.                             else
  508.                                 wasChanged = false;
  509.                 
  510.                 if (wasChanged)
  511.                     {
  512.                         (*aSection)->fCount = (*aSection)->fEnd - (*aSection)->fStart;
  513.                         
  514.                         if (theDoc->showBorders)
  515.                             { /* Force an update of the borders - later*/
  516.                                 GetPort(&oldPort);
  517.                                 SetPort(theDoc->theWindow);
  518.                                 
  519.                                 SetSelectionRgn(theDoc->theText,
  520.                                                                 oldSectionStart,
  521.                                                                 oldSectionEnd,
  522.                                                                 &(*aSection)->fBorderRgn);
  523.                                 InvalRgn((*aSection)->fBorderRgn);
  524.                                 
  525.                                 SetPort(oldPort);
  526.                             }
  527.                             
  528.                     }
  529.  
  530.                 aSection = (*aSection)->fNextSection;
  531.             }
  532.     }  /* DoSectionRecalc */
  533.             
  534. /**-----------------------------------------------------------------------
  535. Name:             ReadAnEdition
  536. Purpose:        Read the latest version of an edition from disk.
  537. -----------------------------------------------------------------------**/
  538.  
  539. #pragma segment Editions
  540.  
  541. pascal void ReadAnEdition(SectionHandle mySectHdl)
  542.     {
  543.         SectHandle    aSectHandle;
  544.         EditionRefNum theRefNum;
  545.         OSErr         err;
  546.         Ptr           p;
  547.         Handle        theStylHandle;
  548.         Size          cutSize;
  549.         Size          stylSize;
  550.         OSErr         stylErr;
  551.         
  552.         p = nil;
  553.         theStylHandle = nil;
  554.         
  555.         if (!mySectHdl)
  556.             {
  557.                 ShowError((unsigned char *)"\pmySectHdl is NIL", 0);
  558.                 return;
  559.             }
  560.  
  561.         aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  562.         if (!aSectHandle)
  563.             {
  564.                 ShowError((unsigned char *)(unsigned char *)"\paSectHandle is NIL", 0);
  565.                 return;
  566.             }
  567.  
  568.         GetDateTime(&(*mySectHdl)->mdDate);
  569.  
  570.         /*read a subscriber in from disk.    Usually in response to a sectionread event*/
  571.         
  572.         err = OpenEdition(mySectHdl, &theRefNum);
  573.  
  574.         if (err)
  575.             {
  576.                 ShowError((unsigned char *)"\pOpenEdition in ReadAnEdition", err);
  577.                 return;
  578.             }
  579.  
  580.         err = EditionHasFormat(theRefNum, 'TEXT', &cutSize);
  581.         if (err)
  582.             {
  583.                 ShowError((unsigned char *)"\pEditionHasFormat in ReadAnEdition", err);
  584.                 return;
  585.             }
  586.             
  587.         stylErr = EditionHasFormat(theRefNum, 'styl', &stylSize);
  588.  
  589.         err = SetEditionFormatMark(theRefNum, 'TEXT', 0);
  590.         if (err)
  591.             {
  592.                 ShowError((unsigned char *)"\pSetEditionFormatMark in ReadAnEdition", err);
  593.                 return;
  594.             }
  595.  
  596.         /*set up a buffer for the text we're going to read in*/
  597.         p = NewPtr(cutSize);
  598.         if (!p)
  599.             {
  600.                 ShowError((unsigned char *)"\pInsufficient memory to read edition", MemError());
  601.                 return;
  602.             }
  603.             
  604.         err = ReadEdition(theRefNum, 'TEXT', p, &cutSize);
  605.  
  606.         if (err)
  607.             {
  608.                 ShowError((unsigned char *)"\pReadEdition", err);
  609.                 return;
  610.             }
  611.             
  612.         if (!stylErr)
  613.             {
  614.                 theStylHandle = NewHandle(stylSize);
  615.                 stylErr = SetEditionFormatMark(theRefNum, 'styl', 0);
  616.                 if (!stylErr)
  617.                     if (theStylHandle)
  618.                         {
  619.                             HLock(theStylHandle);
  620.                             stylErr = ReadEdition(theRefNum, 'styl', *theStylHandle, &stylSize);
  621.                             HUnlock(theStylHandle);
  622.                         }
  623.             }
  624.  
  625.         err = CloseEdition(theRefNum, true);
  626.         if (err)
  627.             {
  628.                 ShowError((unsigned char *)"\pCloseEdition", err);
  629.                 return;
  630.             }
  631.             
  632.         /*
  633.             Ensure this section has a region and invalidate the old region
  634.         */
  635.         
  636.         if ((*aSectHandle)->fBorderRgn == nil)
  637.             (*aSectHandle)->fBorderRgn = NewRgn();
  638.  
  639.         SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  640.                                         (*aSectHandle)->fStart,
  641.                                         (*aSectHandle)->fEnd,
  642.                                         &(*aSectHandle)->fBorderRgn);
  643.                                         
  644.         InvalRgn((*aSectHandle)->fBorderRgn);
  645.         
  646.         /*now insert the text in the right place by setting the selection range*/
  647.         /*we want this to act like paste, but without putting the contents on the clipboard*/
  648.         /*so we have to delete the current selection range and then insert our new text*/
  649.         
  650.         /*
  651.             Also fixup section info. for other moved sections
  652.         */
  653.  
  654.         TESetSelect((*aSectHandle)->fStart,
  655.                                 (*aSectHandle)->fEnd,
  656.                                 ((*aSectHandle)->fDocument)->theText);
  657.                                 
  658.         DoSectionRecalc((*aSectHandle)->fDocument, cutSize);
  659.                                         
  660.         TEDelete(((*aSectHandle)->fDocument)->theText);
  661.         TEStylInsert(p, cutSize, (StScrpHandle)theStylHandle, ((*aSectHandle)->fDocument)->theText);
  662.  
  663.         /*
  664.             Now a little fix up - if the section was previously empty the
  665.             DoSectionRecalc will have put the text in before the section.
  666.             It's like that so you can type in before a subscriber in an
  667.             otherwise empty document. So now pull the start of this section
  668.             back to include the text we just added.
  669.         */
  670.         
  671.         (*aSectHandle)->fStart = (*aSectHandle)->fEnd - cutSize;
  672.         
  673.         /*
  674.             Force redraw of this region
  675.         */
  676.         
  677.         SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  678.                                         (*aSectHandle)->fStart,
  679.                                         (*aSectHandle)->fEnd,
  680.                                         &(*aSectHandle)->fBorderRgn);
  681.                                         
  682.         InvalRgn((*aSectHandle)->fBorderRgn);
  683.         
  684.         DisposPtr(p);
  685.         
  686.         if (theStylHandle)
  687.             DisposHandle(theStylHandle);
  688.     }
  689.  
  690. /**-----------------------------------------------------------------------
  691. Name:             WriteAnEdition
  692. Purpose:        Write out the latest version of an Edition.
  693.                         Called on a Save and on selecting WriteEdition now from
  694.                         the Publisher Options dialog.
  695. -----------------------------------------------------------------------**/
  696.  
  697. #pragma segment Editions
  698.  
  699. pascal void WriteAnEdition(SectionHandle mySectHdl)
  700.   {
  701.         OSErr           err;
  702.         SectHandle      aSectHandle;
  703.         EditionRefNum   theRefNum;
  704.         Handle          aHandle;
  705.         StScrpHandle    theStylHandle;
  706.         short           oldSelStart;
  707.         short           oldSelEnd;
  708.         FSSpecPtr       theFSSpecPtr;
  709.         TEHandle        myText;
  710.         
  711.         aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  712.         /*alter the modification date for the section*/
  713.         GetDateTime(&(*mySectHdl)->mdDate);
  714.         /*write out the edition.  Assume that it is a publisher for now*/
  715.         /*subscribers will be opened for writing with OpenEdition*/
  716.         
  717.         if (((*aSectHandle)->fDocument)->everSaved == false)
  718.             theFSSpecPtr = nil;
  719.         else
  720.             theFSSpecPtr = &((*aSectHandle)->fDocument)->theFSSpec;
  721.             
  722.         err = OpenNewEdition( mySectHdl,
  723.                                                   SVEditAppSig,
  724.                                                     theFSSpecPtr,
  725.                                                     &theRefNum);
  726.         if (err)
  727.             {
  728.                 ShowError((unsigned char *)"\pOpenNewEdition", err);
  729.                 return;
  730.             }
  731.  
  732.         err = SetEditionFormatMark(theRefNum, 'TEXT', 0);
  733.         if (err)
  734.             {
  735.                 ShowError((unsigned char *)"\pSetEditionFormatMark", err);
  736.                 return;
  737.             }
  738.  
  739.         /*now get a handle to the text to be written out*/
  740.         /*use the same start and end positions for now, increasing and decreasing*/
  741.         /*the selection will be implemented later*/
  742.  
  743.         aHandle = GetHandleToText(((*aSectHandle)->fDocument)->theText,
  744.                                                             (*aSectHandle)->fStart,
  745.                                                             (*aSectHandle)->fEnd);
  746.         HLock(aHandle);
  747.  
  748.         /*make sure the count is up to date*/
  749.         (*aSectHandle)->fCount = (*aSectHandle)->fEnd - (*aSectHandle)->fStart;
  750.  
  751.         err = WriteEdition(theRefNum, 'TEXT', *aHandle, (*aSectHandle)->fCount);
  752.         if (err)
  753.             {
  754.                 ShowError((unsigned char *)"\pWriteEdition", err);
  755.                 return;
  756.             }
  757.         HUnlock(aHandle);
  758.         
  759.         myText = ((*aSectHandle)->fDocument)->theText;
  760.         
  761.         oldSelStart   = (*myText)->selStart;
  762.         oldSelEnd     = (*myText)->selEnd;
  763.         
  764.         TESetSelect((*aSectHandle)->fStart,
  765.                     (*aSectHandle)->fEnd,
  766.                                 myText);
  767.                                 
  768.         theStylHandle = GetStylScrap(myText);
  769.         
  770.         TESetSelect(oldSelStart,oldSelEnd, myText);
  771.         
  772.         if (theStylHandle)
  773.             {
  774.                 err = SetEditionFormatMark(theRefNum, 'styl', 0);
  775.                 if (err)
  776.                     {
  777.                         ShowError((unsigned char *)"\pSetEditionFormatMark for styl", err);
  778.                         return;
  779.                     }
  780.                 HLock((Handle)theStylHandle);
  781.                 
  782.                 err = WriteEdition(theRefNum,
  783.                                                      'styl',
  784.                                                      (Ptr)*theStylHandle,
  785.                                                      GetHandleSize((Handle)theStylHandle));
  786.                 HUnlock((Handle)theStylHandle);
  787.             }
  788.             
  789.         /*remember to save the section and alias records as resources later*/
  790.         
  791.         /*now close the edition*/
  792.         
  793.         err = CloseEdition(theRefNum, true);
  794.         if (err)
  795.             {
  796.                 ShowError((unsigned char *)"\pCloseEdition", err);
  797.                 return;
  798.             }
  799.  
  800.         /*
  801.             Clean Up
  802.         */
  803.         
  804.         DisposHandle(aHandle);
  805.         if (theStylHandle)
  806.             DisposHandle((Handle)theStylHandle);    
  807.         
  808.     }     /*WriteAnEdition*/
  809.  
  810. /**-----------------------------------------------------------------------
  811.     Name:             WriteAllEditions
  812.     Purpose:        Go down the list and call WriteAnEdition
  813. -----------------------------------------------------------------------**/
  814.  
  815. #pragma segment  Editions
  816.  
  817. pascal void WriteAllEditions(DPtr aDocument)
  818.   {
  819.         SectHandle      aSection;
  820.         SectionHandle   EMSection;
  821.  
  822.         /*called on a Save, to write out all editions*/
  823.         aSection = aDocument->firstSection;
  824.         
  825.         while (aSection)
  826.             {
  827.                 EMSection = (*aSection)->fSectHandle;
  828.                 if ((*EMSection)->kind == stPublisher)
  829.                     WriteAnEdition(EMSection);
  830.                 aSection = (*aSection)->fNextSection;
  831.             }
  832.     }
  833.  
  834. /**-----------------------------------------------------------------------
  835. Name:             DeRegisterAllSections
  836. Purpose:        Called on cancel Publisher/Subscriber and on a close.
  837. -----------------------------------------------------------------------**/
  838.  
  839. #pragma segment Editions
  840.  
  841. pascal void DeRegisterAllSections(DPtr aDoc)
  842.   {
  843.         SectHandle      aSection;
  844.         SectionHandle   EMSection;
  845.         OSErr           err;
  846.  
  847.         aSection = aDoc->firstSection;
  848.         while (aSection)
  849.             {
  850.                 EMSection = (*aSection)->fSectHandle;
  851.                 err = UnRegisterSection(EMSection);
  852.                 aSection = (*aSection)->fNextSection;
  853.             }
  854.     }
  855.  
  856. /**-----------------------------------------------------------------------
  857. Name:             GetHandleToText
  858. Purpose:        Get a handle to the current text selection.
  859.                         Used to provide a preview on Create Publisher...
  860. -----------------------------------------------------------------------**/
  861.  
  862. #pragma segment Editions
  863.  
  864. pascal Handle GetHandleToText(TEHandle aTEHandle, short theStart, short theEnd)
  865.   {
  866.         OSErr     err;
  867.         Handle    myHandle;
  868.         Ptr       p;
  869.     
  870.         HLock((*aTEHandle)->hText);
  871.         p  = *((*aTEHandle)->hText);
  872.         p  += theStart;
  873.         err = PtrToHand(p, &myHandle, (theEnd - theStart));
  874.         HUnlock((*aTEHandle)->hText);
  875.         return(myHandle);
  876.     } /* GetHandleToText */
  877.  
  878. /**-----------------------------------------------------------------------
  879.         Name:             FindLine
  880.         Purpose:        Find the line a character is in.
  881.                                 Used to find to calculate the region to use for the Publisher/
  882.                                 Subscriber borders.
  883.     -----------------------------------------------------------------------**/
  884.  
  885. #pragma segment Editions
  886.  
  887. pascal short FindLine(short thePos,TEHandle theTEHandle)
  888.   {
  889.         short    index;
  890.         short    theFirstPos;
  891.         short    theNextPos;
  892.  
  893.         index = 0;
  894.  
  895.         do {
  896.             theFirstPos = (*theTEHandle)->lineStarts[index];
  897.             theNextPos  = (*theTEHandle)->lineStarts[index + 1];
  898.             index++;
  899.         }while (! (((thePos >= theFirstPos) && (thePos < theNextPos)) || 
  900.                     (index > (*theTEHandle)->nLines)));
  901.                     
  902.         return(index);
  903.     }
  904.  
  905. /**-----------------------------------------------------------------------
  906.         Name:             DrawSelectionRgn
  907.         Purpose:        Given a text handle and a start and end position this routine
  908.                                 will draw a section border around the selected text.
  909.                                 Must allow for the case when the section has no text in it-
  910.                                 but we still want to show it as a published section
  911.  -----------------------------------------------------------------------**/
  912.  
  913.  pascal void DrawSelectionRegion(TEHandle theTEHandle,
  914.                                                                short    posStart,
  915.                                                              short    posEnd)                
  916.                                                              
  917.      { 
  918.       RgnHandle  theSelRgn;
  919.     
  920.     theSelRgn = NewRgn();
  921.         
  922.         SetSelectionRgn(theTEHandle, posStart, posEnd,&theSelRgn);
  923.         FrameRgn(theSelRgn);
  924.         
  925.         DisposeRgn(theSelRgn);
  926.         
  927.     } /* DrawSelectionRegion */
  928.     
  929. /**-----------------------------------------------------------------------
  930.         Name:             SetSelectionRgn
  931.         Purpose:        Given a text handle and a start and end position this routine
  932.                                 will return the region which is necessary to draw a section
  933.                                 border around the selected text.
  934.                                 Must allow for the case when the section has no text in it-
  935.                                 but we still want to show it as a published section
  936.  -----------------------------------------------------------------------**/
  937.  
  938. #pragma segment Editions
  939.  
  940. pascal void SetSelectionRgn(TEHandle  theTEHandle,
  941.                                                         short     posStart,
  942.                                                         short     posEnd,
  943.                                                         RgnHandle *theSelRgn)
  944.  
  945.     { 
  946.         Point           theStart;
  947.         Point           theEnd;
  948.         short           startLine;
  949.         short           endLine;
  950.         Rect            theRect;
  951.         short           theLeft;
  952.         short           theRight;
  953.         short           theBottom;
  954.         short           theTop;
  955.         short           slineHeight;
  956.         short           elineHeight;
  957.         short           fontAscent;
  958.         TextStyle       theTStyle;
  959.             
  960.         /*first of all find out if the text is on the same line*/
  961.         startLine = FindLine(posStart, theTEHandle);
  962.         endLine   = FindLine(posEnd, theTEHandle);
  963.     
  964.         theStart = TEGetPoint(posStart, theTEHandle);
  965.         theEnd   = TEGetPoint(posEnd, theTEHandle);
  966.     
  967.     /*
  968.     Get the line height info
  969.     */
  970.         TEGetStyle(posStart, &theTStyle, &slineHeight, &fontAscent, theTEHandle);
  971.         TEGetStyle(posEnd,   &theTStyle, &elineHeight, &fontAscent, theTEHandle);
  972.     
  973.         if (startLine == endLine)
  974.             {
  975.                 /*use the start and end points to form the rectangle and draw this into the region*/
  976.                 theStart.v -= slineHeight;
  977.                 Pt2Rect(theStart, theEnd, &theRect);
  978.                 InsetRect(&theRect, - 1, - 1);
  979.                 RectRgn(*theSelRgn, &theRect);
  980.             }
  981.         else
  982.             {
  983.                 theLeft  = (*theTEHandle)->destRect.left;
  984.                 theRight = (*theTEHandle)->destRect.right;
  985.                 theTop   = theStart.v - slineHeight;
  986.                 theBottom  = theEnd.v;
  987.                 OpenRgn();
  988.                 MoveTo(theStart.h, theStart.v - slineHeight);
  989.                 LineTo(theRight, theStart.v - slineHeight);
  990.                 LineTo(theRight, theEnd.v - elineHeight);
  991.                 LineTo(theEnd.h, theEnd.v - elineHeight);
  992.                 LineTo(theEnd.h, theEnd.v);
  993.                 LineTo(theLeft, theEnd.v);
  994.                 LineTo(theLeft, theStart.v);
  995.                 LineTo(theStart.h, theStart.v);
  996.                 LineTo(theStart.h, theStart.v - slineHeight);
  997.                 CloseRgn(*theSelRgn);
  998.             }
  999.     
  1000.         InsetRgn(*theSelRgn, - 2, - 2);
  1001.     
  1002.     }
  1003.  
  1004. /**-----------------------------------------------------------------------
  1005.         Name:             ShowSectionBorders
  1006.         Purpose:        Show the borders for all the sections in a document.
  1007.                                 Show a Publisher border in 50% gray, a subscriber in 75% gray
  1008.  -----------------------------------------------------------------------**/
  1009.  
  1010. #pragma segment Editions
  1011.  
  1012. pascal void ShowSectionBorders(DPtr aDoc)
  1013.   {
  1014.         SectHandle aSection;
  1015.  
  1016.         PenNormal();
  1017.         PenSize(3, 3);
  1018.         PenPat(&qd.gray);
  1019.         aSection = aDoc->firstSection;
  1020.         while (aSection)
  1021.             {
  1022.                 if ((*aSection)->fBorderRgn)
  1023.                     {
  1024.                         SetSelectionRgn(((*aSection)->fDocument)->theText, 
  1025.                                                         (*aSection)->fStart, 
  1026.                                                         (*aSection)->fEnd,
  1027.                                                         &(*aSection)->fBorderRgn);
  1028.                                                         
  1029.                         if ((*(*aSection)->fSectHandle)->kind == stPublisher)
  1030.                             PenPat(&qd.gray);
  1031.                         else
  1032.                             PenPat(&qd.dkGray);
  1033.                             
  1034.                         FrameRgn((*aSection)->fBorderRgn);
  1035.                         PenNormal();
  1036.                     }
  1037.                 aSection = (*aSection)->fNextSection;
  1038.             }
  1039.         PenNormal();
  1040.     }
  1041.  
  1042. /**-----------------------------------------------------------------------
  1043.         Name:             RecalcBorders
  1044.         Purpose:        Recalculate all the borders for the sections in a document.
  1045.  -----------------------------------------------------------------------**/
  1046.  
  1047. #pragma segment Editions
  1048.  
  1049. pascal void RecalcBorders(DPtr aDoc, Boolean invalidate)
  1050.   {
  1051.         SectHandle  aSection;
  1052.  
  1053.         /*go down the section list and recalculate all the borders*/
  1054.         aSection = aDoc->firstSection;
  1055.         while (aSection)
  1056.             {
  1057.                 if ((*aSection)->fBorderRgn)
  1058.                     {
  1059.                         if (invalidate)
  1060.                             InvalRgn((*aSection)->fBorderRgn);
  1061.                         
  1062.                         SetSelectionRgn(((*aSection)->fDocument)->theText,
  1063.                                         (*aSection)->fStart,
  1064.                                                         (*aSection)->fEnd,
  1065.                                                         &(*aSection)->fBorderRgn);
  1066.                                                         
  1067.                         if (invalidate)
  1068.                             InvalRgn((*aSection)->fBorderRgn);
  1069.                     }
  1070.                 aSection = (*aSection)->fNextSection;
  1071.             }
  1072.     }
  1073.  
  1074. /**-----------------------------------------------------------------------
  1075.         Name:             GetSection
  1076.         Purpose:        Given a start and end of a selection- return the section
  1077.                                 handle if it is in a Publisher or Subscriber.
  1078.  -----------------------------------------------------------------------**/
  1079.  
  1080. #pragma segment Editions
  1081.  
  1082. pascal SectHandle GetSection(short theStartPos, short theEndPos, DPtr aDoc)
  1083.   {
  1084.         SectHandle   foundSection;
  1085.         SectHandle   aSection;
  1086.  
  1087.         /*returns the section handle for the section between theStartPos and theEndPos*/
  1088.         
  1089.         foundSection = nil;
  1090.         
  1091.         aSection = aDoc->firstSection;
  1092.         while (aSection)
  1093.             {
  1094.                 if ((theStartPos >= (*aSection)->fStart) && (theEndPos <= (*aSection)->fEnd))
  1095.                     foundSection = aSection;
  1096.                 aSection = (*aSection)->fNextSection;
  1097.             }
  1098.             
  1099.         return(foundSection);
  1100.     }
  1101.  
  1102. /**-----------------------------------------------------------------------
  1103.         Name:             DoTEPasteSectionRecalc
  1104.         Purpose:        Keeps track of the positions of the sections call before a 
  1105.                     TEPaste or TEStylPaste.
  1106.  -----------------------------------------------------------------------**/
  1107.  
  1108. pascal void DoTEPasteSectionRecalc(DPtr theDoc)
  1109.     {
  1110.         short toAdd;
  1111.         
  1112.         toAdd = TEGetScrapLen();
  1113.         DoSectionRecalc(theDoc, toAdd);
  1114.     }  /* DoTEPasteSectionRecalc */
  1115.             
  1116. /**-----------------------------------------------------------------------
  1117.         Name:             DoTEDeleteSectionRecalc
  1118.         Purpose:        Keeps track of the positions of the sections call before a 
  1119.                     TEDelete.
  1120.  -----------------------------------------------------------------------**/
  1121.  
  1122. pascal void DoTEDeleteSectionRecalc(DPtr theDoc)
  1123.     {
  1124.         DoSectionRecalc(theDoc, 0);
  1125.     }  /* DoTEDeleteSectionRecalc */
  1126.             
  1127. /**-----------------------------------------------------------------------
  1128.         Name:             DoTECutSectionRecalc
  1129.         Purpose:        Keeps track of the positions of the sections call before a 
  1130.                     TECut.
  1131.  -----------------------------------------------------------------------**/
  1132.  
  1133. pascal void DoTECutSectionRecalc(DPtr theDoc)
  1134.     {
  1135.         DoSectionRecalc(theDoc, 0);
  1136.     }  /* DoTEDeleteSectionRecalc */
  1137.             
  1138. /**-----------------------------------------------------------------------
  1139.         Name:             DoTEKeySectionRecalc
  1140.         Purpose:        Keeps track of the positions of the sections call before a 
  1141.                     TECut.
  1142.  -----------------------------------------------------------------------**/
  1143.  
  1144. pascal void DoTEKeySectionRecalc(DPtr theDoc,char theChar)
  1145.     {
  1146.         short     toAdd;
  1147.         short     oldStart;
  1148.         
  1149.         if (!KeyOKinSubscriber(theChar)) /* is it a cursor motion key? - yes = ignore */
  1150.             {
  1151.                 if (theChar==8)
  1152.                     if ((*(theDoc->theText))->selStart<(*(theDoc->theText))->selEnd)
  1153.                         toAdd = 0;
  1154.                     else
  1155.                         {
  1156.                             toAdd = -1;
  1157.                             oldStart = (*(theDoc->theText))->selStart;
  1158.                             
  1159.                             (*(theDoc->theText))->selStart = GreaterOf(oldStart-1,0);
  1160.                             DoSectionRecalc(theDoc, 0);
  1161.                             (*(theDoc->theText))->selStart = oldStart;
  1162.                         }
  1163.                 else
  1164.                     toAdd = 1;
  1165.                     
  1166.                 if (toAdd!=-1)
  1167.                     DoSectionRecalc(theDoc, toAdd);
  1168.             }    
  1169.     }  /* DoTEKeySectionRecalc */
  1170.  
  1171. /**-----------------------------------------------------------------------
  1172.         Name:             GetEditionContainer
  1173.         Purpose:        Gets the Edition Container to put the edition into.
  1174.                                 The main user interface stuff. 
  1175.                                 Puts up the new publisher dialog.
  1176.                                 Should check kAEInteractWithUser etc.
  1177.  -----------------------------------------------------------------------**/
  1178.  
  1179. #pragma segment Main
  1180.  
  1181. pascal OSErr GetEditionContainer(DPtr theDoc, FSSpec *theFSSpec)
  1182.   {
  1183.         OSErr             err;
  1184.         NewPublisherReply myReply;
  1185.         short             theStart;
  1186.         short             theEnd;
  1187.         Handle            myHandle;
  1188.         TEHandle          myText;
  1189.  
  1190.         err = noErr;
  1191.  
  1192.         /*get default editionContainer to use, using last volume and folder*/
  1193.         
  1194.         myReply.container.thePart = kPartsNotUsed;
  1195.  
  1196.         err = GetLastEditionContainerUsed(&myReply.container);
  1197.         
  1198.         if (err==fnfErr)
  1199.             err = noErr;
  1200.             
  1201.         myText = theDoc->theText;
  1202.         
  1203.         theStart = (*myText)->selStart;
  1204.         theEnd   = (*myText)->selEnd;
  1205.                                         
  1206.         if (err==noErr)    
  1207.             {
  1208.                 /*
  1209.                     Create a handle containing the text to be published for previewing -
  1210.                     need to ask the user where to put the data
  1211.                 */
  1212.                 myHandle = GetHandleToText(myText, theStart, theEnd);
  1213.                 
  1214.                 myReply.usePart       = false;
  1215.                 myReply.preview       = myHandle;
  1216.                 myReply.previewFormat = 'TEXT';
  1217.                 myReply.container.theFile.name[0] = 0; /* Want a proper prompted name here */
  1218.                 HLock(myHandle);
  1219.                 
  1220.                 /* Should take suggested name and avoid dialog if no user interaction */
  1221.                 
  1222.                 err = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  1223.                 
  1224.                 err = NewPublisherDialog(&myReply);
  1225.                 HUnlock(myHandle);
  1226.                 DisposHandle(myHandle);
  1227.             }
  1228.             
  1229.         /*IF user cancelled, THEN exit from this routine*/
  1230.         
  1231.         if (err==noErr)
  1232.             if (myReply.canceled)
  1233.                 err = userCanceledErr; /* User cancelled marker - replace later */
  1234.             
  1235.         if (err==noErr)
  1236.             if (myReply.replacing)
  1237.                 err = FSpDelete(&myReply.container.theFile);
  1238.                 
  1239.         if (err == noErr)
  1240.             *theFSSpec = myReply.container.theFile;
  1241.             
  1242.         return(err);
  1243.     } /*GetEditionContainer*/
  1244.  
  1245.  
  1246. /**-----------------------------------------------------------------------
  1247.         Name:             PublishText
  1248.         Purpose:        Publishes the current selection of theDoc.
  1249.                                 The main user interface stuff. 
  1250.                                 Puts up the new publisher dialog - if theFSSpec=NIL
  1251.                                 Writes the new edition out to disk.
  1252.  -----------------------------------------------------------------------**/
  1253.  
  1254. #pragma segment Main
  1255.  
  1256. pascal OSErr PublishText(DPtr theDoc, FSSpecPtr theFSSpec)
  1257.   {
  1258.         NewPublisherReply myReply;
  1259.         SectionHandle          mySectHdl;
  1260.         OSErr                 err;
  1261.         long                   mysectionID;
  1262.         FSSpecPtr             pubFSSpec;
  1263.         short                 theStart;
  1264.         short                 theEnd;
  1265.         RgnHandle             theRgnHandle;
  1266.                 
  1267.         mysectionID    = theDoc->lastID + 1;
  1268.         theDoc->lastID = mysectionID;
  1269.  
  1270.         /*get default editionContainer to use, using last volume and folder*/
  1271.         
  1272.         myReply.container.thePart = kPartsNotUsed;
  1273.  
  1274.         err = GetLastEditionContainerUsed(&myReply.container);
  1275.         
  1276.         if (err==fnfErr)
  1277.             err = noErr;
  1278.         
  1279.         theStart = (*theDoc->theText)->selStart;
  1280.         theEnd   = (*theDoc->theText)->selEnd;
  1281.  
  1282.         /*don't want to publish an empty section*/
  1283.         
  1284.         if (theEnd - theStart == 0)
  1285.             err = userCanceledErr; 
  1286.                             
  1287.         myReply.container.theFile = *theFSSpec;
  1288.             
  1289.         /*now publish this section*/
  1290.         
  1291.         if (err == noErr)
  1292.             err = CreateEditionContainerFile(&myReply.container.theFile, SVEditAppSig, 0);
  1293.         
  1294.         /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1295.         
  1296.         if (theDoc->everSaved == false)
  1297.             pubFSSpec = nil;
  1298.         else
  1299.             pubFSSpec = &theDoc->theFSSpec;
  1300.  
  1301.         /*get the region to encompass the selection*/
  1302.         
  1303.         theRgnHandle = NewRgn();
  1304.         SetSelectionRgn(theDoc->theText,
  1305.                         (*theDoc->theText)->selStart,
  1306.                                         (*theDoc->theText)->selEnd,
  1307.                                         &theRgnHandle);
  1308.                                         
  1309.         InvalRgn(theRgnHandle);
  1310.  
  1311.         /*create a publisher section*/
  1312.         if (err==noErr)
  1313.             {
  1314.                 err = NewSection(&myReply.container,
  1315.                                                  pubFSSpec,
  1316.                                                  stPublisher,
  1317.                                                  mysectionID,
  1318.                                                  pumOnSave,
  1319.                                                  &mySectHdl);
  1320.  
  1321.                 /*now add this section to our document list*/
  1322.                 
  1323.                 if (err == noErr)
  1324.                     CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, theRgnHandle);
  1325.             }
  1326.  
  1327.         /*now write out the edition to file*/
  1328.         
  1329.         if (err==noErr)
  1330.             WriteAnEdition(mySectHdl);
  1331.             
  1332.         return(err);
  1333.     } /*PublishText*/
  1334.  
  1335. /**-----------------------------------------------------------------------
  1336.         Name:             DoSubscribe
  1337.         Purpose:        Subscribe to a published section. Puts up the subscriber
  1338.                                 dialog, creates and adds the new section.
  1339.  -----------------------------------------------------------------------**/
  1340.  
  1341. #pragma segment  Main
  1342.  
  1343. pascal void DoSubscribe(DPtr theDoc)
  1344.   {
  1345.         NewSubscriberReply myReply;
  1346.         SectionHandle      mySectHdl;
  1347.         long               mysectionID;
  1348.         FSSpecPtr          subFSSpec; /*the fsspec for the subscriber file*/
  1349.         OSErr              err;
  1350.         short              theStart;
  1351.         short              theEnd;
  1352.  
  1353.         mysectionID = theDoc->lastID + 1;
  1354.         theDoc->lastID = mysectionID;
  1355.         err = noErr;
  1356.  
  1357.         /*get default editionContainer to use, using last volume and folder*/
  1358.         /*  myreply.container.thePart := kPartNumberUnknown;*/
  1359.         myReply.formatsMask = kTEXTformatMask;
  1360.         
  1361.         err = GetLastEditionContainerUsed(&myReply.container);
  1362.         if (err && (err !=fnfErr))
  1363.             {
  1364.                 ShowError((unsigned char *)"\pGetLastEditionContainerUsed", err);
  1365.                 return;
  1366.             }
  1367.  
  1368.         /*put up the subscriber dialog*/
  1369.         err = NewSubscriberDialog(&myReply);
  1370.         if (err && (err !=fnfErr))
  1371.             {
  1372.                 ShowError((unsigned char *)"\pNewSubscriberDialog", err);
  1373.                 return;
  1374.             }
  1375.  
  1376.         if (myReply.canceled)
  1377.             return;
  1378.  
  1379.         /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1380.         if (theDoc->everSaved == false)
  1381.             subFSSpec = nil;
  1382.         else
  1383.             subFSSpec = &theDoc->theFSSpec;
  1384.  
  1385.         /*create a publisher section*/
  1386.         err = NewSection(&myReply.container,
  1387.                                          subFSSpec,
  1388.                                          stSubscriber,
  1389.                                          mysectionID,
  1390.                                          sumAutomatic,
  1391.                                          &mySectHdl);
  1392.                                             
  1393.         if (err)
  1394.             {
  1395.                 ShowError((unsigned char *)"\pNewSection", err);
  1396.                 return;
  1397.             }
  1398.  
  1399.         theStart = (*theDoc->theText)->selStart;
  1400.         theEnd   = (*theDoc->theText)->selEnd;
  1401.  
  1402.         /*now add this section to our document list*/
  1403.  
  1404.         CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, nil);
  1405.  
  1406.         /*read the subscriber in from disk*/
  1407.  
  1408.         ReadAnEdition(mySectHdl);
  1409.  
  1410.     }  /*DoSubscribe*/
  1411.  
  1412. /**-----------------------------------------------------------------------
  1413.         Name:             DoSectionOptions
  1414.         Purpose:        Put up the section option dialogs for a publisher
  1415.                                 or subscriber.    Handle all the various options.
  1416.                                 Note that 'Find Publisher' doesn't work yet.
  1417.  -----------------------------------------------------------------------**/
  1418.  
  1419. #pragma segment  Main
  1420.  
  1421. pascal void DoSectionOptions(DPtr theDoc)
  1422.   {
  1423.         OSErr               err;
  1424.         SectionOptionsReply reply;
  1425.         EditionInfoRecord   theInfo;
  1426.         SectHandle          currSection;
  1427.         
  1428.         currSection = GetSection((*theDoc->theText)->selStart,
  1429.                                                          (*theDoc->theText)->selEnd,
  1430.                                                          theDoc);
  1431.  
  1432.         reply.sectionH = (*currSection)->fSectHandle;
  1433.         err = SectionOptionsDialog(&reply);
  1434.         if (!reply.canceled)
  1435.             {
  1436.                 /*find out IF there is any action needed*/
  1437.                 if (reply.action == 'read')
  1438.                 /*read the latest version of a subscriber*/
  1439.                     ReadAnEdition((*currSection)->fSectHandle);
  1440.                 else
  1441.                     if (reply.action == 'writ')
  1442.                     /*write out the latest version of a publisher to disk*/
  1443.                         WriteAnEdition((*currSection)->fSectHandle);
  1444.                     else
  1445.                         if (reply.action == 'goto') /*goto a published section*/
  1446.                             {
  1447.                                 err = GetEditionInfo((*currSection)->fSectHandle, &theInfo);
  1448.                                 
  1449.                                 if (err)
  1450.                                     ShowError((unsigned char *)"\pGetEditionInfo", err);
  1451.                                     
  1452.                                 err = GoToPublisherSection(&theInfo.container);
  1453.                                 
  1454.                                 if (err)
  1455.                                     ShowError((unsigned char *)"\pGotoPublisherSection", err);
  1456.                             }
  1457.                         else
  1458.                             if (reply.action == 'cncl') /*cancel a publisher or subscriber*/
  1459.                                 {
  1460.                                     /*unRegister the section and delete from our own list*/
  1461.                                     /*should have a free PROCEDURE which frees the structures*/
  1462.                                     /*associated with a section*/
  1463.                                     err = UnRegisterSection((*currSection)->fSectHandle);
  1464.                                     DeleteASection(currSection, theDoc);
  1465.  
  1466.                                     /*IF this is the ONLY publisher writing data to this edition*/
  1467.                                     /*we should delete the container file as well*/
  1468.                                 }
  1469.             }
  1470.     }
  1471.